/* file: zm_exec.c */

#include "zm.h"
#include "zm_exec.h"

int exec_code()
{
    int pc = 0;
    code_seg curr_code = code_mem[pc];
    OP_CODE op;
    int data1, data2;
    int temp1, temp2, flag1, flag2, temp;
    
    op = curr_code.op_code;
    
    top = 0;
    while(op != -1)
    {
        data1 = curr_code.data1.data;
        data2 = curr_code.data2.data;
        flag1 = curr_code.data1.flag;
        flag2 = curr_code.data2.flag;
        switch(op)
        {
            case MOV:
                 if((flag1 == REG_FLAG) && (flag2 == DATA_FLAG))
                     reg[data1] = data2;
                 else if((flag1 == REG_FLAG) && (flag2 == MEM_FLAG))
                     reg[data1] = data_mem[data2];
                 else if((flag1 == MEM_FLAG) && (flag2 == REG_FLAG))
                     data_mem[data1] = reg[data2];
                 else 
                     printf("error\n");
                 pc++;
                 break; 
            case PUSH:
                 if(flag1 == REG_FLAG)
                     stack_mem[top++] = reg[data1];
                 pc++;
                 break;
            case POP:
                 if(flag1 == REG_FLAG)
                     reg[data1] = stack_mem[--top] ;
                 pc++;
                 break;
            case XCHG:
                 if((flag1 == REG_FLAG) && (flag2 == REG_FLAG))
                     temp = reg[data1], reg[data1] = reg[data2], reg[data2] = temp;
                 pc++;
                 break;
           case ADD:
                 if((flag1 == REG_FLAG) && (flag2 == REG_FLAG))
                     reg[data1] = reg[data1] + reg[data2];
                 pc++;
                 break;
           case SUB:
                if((flag1 == REG_FLAG) && (flag2 == REG_FLAG))
                     reg[data1] = reg[data1] - reg[data2];
                 pc++;
                 break;
           case MUL:
                 if((flag1 == REG_FLAG) && (flag2 == REG_FLAG))
                     reg[data1] = reg[data1] * reg[data2];
                 pc++;
                 break;
           case DIV:
                 if((flag1 == REG_FLAG) && (flag2 == REG_FLAG))
                     reg[data1] = reg[data1] / reg[data2];
                 pc++;
                 break;
           case JNE:
                 if(flag1 == MEM_FLAG)
                     if(reg[0] != 0)
                         pc = data1;
                      else
                         pc++;
                 break;
          case JLS:
                 if(flag1 == MEM_FLAG)
                     if(reg[0] < 0)
                         pc = data1;
                      else
                         pc++;
                 break;
           case JLE:
                 if(flag1 == MEM_FLAG)
                     if(reg[0] <= 0)
                         pc = data1;
                      else
                         pc++;
                 break;
           case  JGT:
                 if(flag1 == MEM_FLAG)
                     if(reg[0] > 0)
                         pc = data1;
                      else
                         pc++;
                 break;
           case JGE:
                 if(flag1 == MEM_FLAG)
                     if(reg[0] >= 0)
                         pc = data1;
                      else
                         pc++;
                 break;
           case JEQ:
                 if(flag1 == MEM_FLAG)
                     if(reg[0] == 0)
                         pc = data1;
                      else
                         pc++;
                 break;
           case  JMP:
                 if(flag1 == MEM_FLAG)
                     pc = data1;
                 break;
           case OUT:
                 printf("The result is %d\n", reg[0]);
                 pc++;
                 break;
           case IN:
                 printf("Please input a integer number:");
                 scanf("%d",&reg[0]);
                 printf("\n");
                 pc++;
                 break;
        }
        curr_code = code_mem[pc];
        op = curr_code.op_code;
    }
    return 1;

}